package tech.konata.yukkuri.gui;

import lombok.Getter;
import lombok.SneakyThrows;
import tech.konata.yukkuri.Yukkuri;
import tech.konata.yukkuri.utils.MultiThreadingUtil;
import tech.konata.yukkuri.utils.resource.ResourceUtil;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.FontUIResource;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.PrintWriter;
import java.io.StringBufferInputStream;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicBoolean;

public class YukkuriGui extends JFrame {

    final Font font = new Font("微软雅黑", Font.PLAIN, 14);

    JPanel basePanel;
    JTextArea textArea;
    JComboBox<VoiceType> voiceType;
    JCheckBox echo, boyomi;
    JSlider speed, volume;
    JButton generate;
    JLabel status, subStatus;

    AtomicBoolean inProgress = new AtomicBoolean(false);

    @SneakyThrows
    public YukkuriGui() {

        super("Yukkuri Gui - BiliBili @ IzumiiKonata");

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(640, 480);

        this.setLocationRelativeTo(null);
        this.setResizable(false);
        this.setIconImage(ResourceUtil.ICON);
        JFrame.setDefaultLookAndFeelDecorated(true);
//        UIManager.setLookAndFeel(new WindowsLookAndFeel());

        basePanel = new JPanel();

        basePanel.setLayout(null);
        basePanel.setBounds(0, 0, 640, 480);

        textArea = new JTextArea();

        textArea.setFont(font);
        textArea.setBounds(0, 0, 640, 300);
        textArea.setLineWrap(false);
        textArea.setEditable(true);

        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        scrollPane.setBounds(2, 2, 620, 300);

        basePanel.add(scrollPane);

        JLabel comboBoxLabel = new JLabel("配音类型: ");
        comboBoxLabel.setFont(font);
        comboBoxLabel.setBounds(2, 310, 120, 20);

        basePanel.add(comboBoxLabel);

        voiceType = new JComboBox<>(VoiceType.values());
        voiceType.setFont(font);
        voiceType.setBounds(2, 330, 120, 30);

        basePanel.add(voiceType);

        JLabel echoLabel = new JLabel("回声: ");
        echoLabel.setFont(font);
        echoLabel.setBounds(140, 334, 60, 20);

        echo = new JCheckBox();
        echo.setFont(font);
        echo.setBounds(180, 330, 40, 30);

        basePanel.add(echo);
        basePanel.add(echoLabel);

        JLabel boyomiLabel = new JLabel("棒读: ");
        boyomiLabel.setFont(font);
        boyomiLabel.setBounds(220, 334, 60, 20);

        boyomi = new JCheckBox();
        boyomi.setFont(font);
        boyomi.setBounds(260, 330, 40, 30);

        basePanel.add(boyomi);
        basePanel.add(boyomiLabel);

        speed = new JSlider(JSlider.HORIZONTAL, 50, 300, 100);
        speed.setMinorTickSpacing(10);
        speed.setMajorTickSpacing(10);
        speed.setSnapToTicks(true);
        speed.setBounds(300, 330, 120, 30);

        JLabel speedLabel = new JLabel("速度: " + speed.getValue());
        speedLabel.setFont(font);
        speedLabel.setBounds(300, 310, 120, 20);

        speed.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                speedLabel.setText("速度: " + speed.getValue());
            }
        });

        basePanel.add(speed);
        basePanel.add(speedLabel);

        volume = new JSlider(JSlider.HORIZONTAL, 10, 200, 100);
        volume.setMinorTickSpacing(10);
        volume.setMajorTickSpacing(10);
        volume.setSnapToTicks(true);
        volume.setBounds(420, 330, 120, 30);

        JLabel volumeLabel = new JLabel("音量: " + volume.getValue());
        volumeLabel.setFont(font);
        volumeLabel.setBounds(420, 310, 120, 20);

        volume.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                volumeLabel.setText("音量: " + volume.getValue());
            }
        });

        basePanel.add(volume);
        basePanel.add(volumeLabel);

        generate = new JButton("生成!");
        generate.setBounds(540, 405, 80, 30);

        generate.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                if (textArea.getText().isEmpty()) {
                    showMessageBox("输入为空!");
                    return;
                }

                if (inProgress.get()) {
                    showMessageBox("正在生成!");
                    return;
                }

                MultiThreadingUtil.runAsync(() -> {
                    inProgress.set(true);

                    String[] split = textArea.getText().split("\n");

                    status.setText("状态: 生成中...");

                    for (int i = 0; i < split.length; i++) {

                        try {

                            String text = split[i].trim();

                            subStatus.setText("[" + (i + 1) + "]: 请求中文转片假名中...");

                            String katakana = Yukkuri.getInstance().convertToKatakana(text);

                            System.out.println("[" + (i + 1) + "]: 转换后的片假名: " + katakana);

                            subStatus.setText("[" + (i + 1) + "]: 转换后的片假名: " + katakana);

                            Yukkuri.getInstance().generateAndSavePro(katakana, text, (VoiceType) voiceType.getSelectedItem(), echo.isSelected(), boyomi.isSelected(), speed.getValue(), volume.getValue());

                            subStatus.setText("[" + (i + 1) + "]: OK! 已保存至Yukkuri\\" + text + ".mp3");

                        } catch (Exception ex) {

                            StringWriter sw = new StringWriter();

                            ex.printStackTrace(new PrintWriter(sw));

                            showMessageBox("错误!\n" + sw);

                        }

                    }

                    status.setText("状态: 等待中...");
//                    subStatus.setText("");

                    inProgress.set(false);

                    showMessageBox("转换完成!");
                });

            }

        });

        basePanel.add(generate);

        status = new JLabel("状态: 等待中...");
        status.setBounds(2, 400, 999, 20);
        basePanel.add(status);

        subStatus = new JLabel("");
        subStatus.setBounds(2, 420, 999, 20);
        basePanel.add(subStatus);

        this.setContentPane(basePanel);

        FontUIResource res = new FontUIResource(font);
        UIManager.getLookAndFeelDefaults().put("Button.font", res);
        UIManager.getLookAndFeelDefaults().put("TextField.font", res);
        UIManager.getLookAndFeelDefaults().put("Label.font", res);
        SwingUtilities.updateComponentTreeUI(this);

    }

    private void showMessageBox(String text) {
        JOptionPane.showMessageDialog(this, text, "注意!", JOptionPane.INFORMATION_MESSAGE);
    }

    public void showGui() {
        this.setVisible(true);
        this.toFront();
    }

    @Getter
    public enum VoiceType {

        AT1_F1("f1"),
        AT1_F2("f2"),
        AT1_M1("m1"),
        AT1_M2("m2"),
        AT1_DVD("dvd"),
        AT1_IMD1("imd1"),
        AT1_JGR("jgr"),
        AT1_R1("r1"),
        AT2_RM("rm"),
        AT2_F1C("f1c"),

        // 网页这里显示的是AT2-RM 估计是错了
        AT2_F3A("f3a"),
        AT2_HUSKEY("huskey"),
        AT2_M4B("m4b"),
        AT2_MF1("mf1"),
        AT2_RB2("rb2"),
        AT2_RB3("rb3"),
        AT2_ROBO("robo"),
        AT2_YUKKURI("yukkuri"),
        AT2_F4("f4"),
        AT2_M5("m5"),
        AT2_MF2("mf2"),
        AT2_RM3("rm3"),
        AT10_F1("f1e", 100, 100, 100, 100),
        AT10_F2("f2e", 77, 150, 100, 100),
        AT10_F3("f1e", 100, 100, 61, 148),
        AT10_M1("m1e", 30, 100, 61, 148),
        AT10_M2("m1e", 45, 130, 120, 148),
        AT10_R1("m1e", 30, 20, 190, 148),
        AT10_R2("f2e", 50, 50, 50, 180),
        ;

        private final String type;

        private final boolean extraParameters;

        private int pitch = 0, accent = 0, lmd = 0, fsc = 0;

        VoiceType(String type) {
            this.type = type;
            this.extraParameters = false;
        }

        VoiceType(String type, int pitch, int accent, int lmd, int fsc) {
            this.type = type;
            this.extraParameters = true;
            this.pitch = pitch;
            this.accent = accent;
            this.lmd = lmd;
            this.fsc = fsc;

        }



    }

}
